/*
 * app_task.c
 *
 *  Created on: 2021-01-09
 *  Author: Ocamor
 *
 * Change Logs:
 * Date           Author       Notes
 *
 *
 *----------------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "semphr.h"
#include "app_task.h"
#include "stdlib.h"
#include "task.h"
#include "log.h"
#include "rf_process.h"
#include "common.h"
#include "app_reserve_day.h"
#include "port_ctrl.h"
extern TaskHandle_t  rf_send_task_handler;
extern QueueHandle_t radio_operation_queue;
extern QueueHandle_t flash_operation_queue;
/************************************************
 * @brief    vRfRecvTask
 * @Author   ocamar
 * @DateTime 2021-07-20
 * @version  v1.0
 * @param    parameter              [description]
*************************************************/


uint8_t radio_recviver_cache[64];
extern RAIL_Handle_t railHandle;
uint8_t tmp[64];
void vRadioOperationTask(void *pvParameters)
{
    (void) pvParameters;
    uint32_t no_recviver_radio_msg_tick = 0;
    uint32_t radio_work_idle_tick = 0;
    uint8_t receiver_buffer_lens;
    int8_t rssi = 0;
    radio_operation_t opeartion;
    struct receiver_buffer_s *receiver = NULL;
    while(1)
    {
        if(xQueueReceive( radio_operation_queue, &opeartion, 1000))
        {
            if(RADIO_RECEIVER == opeartion.type)
            {
                receiver = opeartion.radio_rx.buff;
                no_recviver_radio_msg_tick = 0;
                radio_work_idle_tick = 0;
                if(receiver)
                {
                    receiver_buffer_lens = receiver->lens;
                    memcpy(radio_recviver_cache, receiver->buff, receiver_buffer_lens);
                    rssi = receiver->rssi;
                    receiver->used = false;
        //            RAIL_Idle(railHandle,RAIL_IDLE,true);
        //            RAIL_ResetFifo(railHandle,true,true);
        //            RAIL_StartRx(railHandle, 0, NULL);//确定接收后的状态,接收数据后变成IDLE态，因此要手动进入接收##
                    no_recviver_radio_msg_tick = 0;
                    radio_work_idle_tick = 0;
//                    elog_info("recv:%02x%02x%02x%02x", radio_recviver_cache[2], radio_recviver_cache[3], radio_recviver_cache[4], radio_recviver_cache[5]);
                }
                receiver = NULL;
            }
            else if(RADIO_SEND == opeartion.type)
            {
                elog_info("radio send");
                static uint8_t number = 0;
                memset(tmp, number++, sizeof(tmp));
                tmp[0] = 62;
                EFR32_SendPacket(railHandle, tmp, 62, rf_msg_send_wait_success);
            }
        }
        else
        {
            //#define RAIL_RF_STATE_ACTIVE    ((RAIL_RadioState_t) RAIL_RF_STATE_ACTIVE)
            //#define RAIL_RF_STATE_RX        ((RAIL_RadioState_t) RAIL_RF_STATE_RX)
            //#define RAIL_RF_STATE_TX        ((RAIL_RadioState_t) RAIL_RF_STATE_TX)

            RAIL_RadioState_t state = RAIL_GetRadioState(railHandle);
            no_recviver_radio_msg_tick++;
            if(RAIL_RF_STATE_IDLE == state)
            {
                radio_work_idle_tick++;
            }
            else
            {
                radio_work_idle_tick = 0;
            }
        }


        if(no_recviver_radio_msg_tick > 3600 || radio_work_idle_tick > 2)
        {

            RAIL_Idle(railHandle,RAIL_IDLE,true);
            RAIL_ResetFifo(railHandle,true,true);
            RAIL_StartRx(railHandle, 0, NULL);//确定接收后的状态,接收数据后变成IDLE态，因此要手动进入接收##
            if(no_recviver_radio_msg_tick > 3600)
            {
                elog_error("long time no receiver radio message, Re initialize the radio!!!");
            }
            else
            {
                elog_error("long time work in radio idle mode, Re initialize the radio!!!");
            }
            no_recviver_radio_msg_tick = 0;
            radio_work_idle_tick = 0;
        }


    }
}

/************************************************
 * @brief    vRfSendTask
 * @Author   ocamar
 * @DateTime 2021-07-20
 * @version  v1.0
 * @param    parameter              [description]
*************************************************/
#include "app_param_store.h"

void vFlashOperationTask(void *pvParameters)
{
    store_msg_t store;
    (void) pvParameters;
    flash_operation_t opeartion;
    uint32_t port = get_port_opt();
    uint32_t time_remain = get_reserved_days();

    if(get_reserved_days())
    {
        //授权时间生效,允许使能端口
        port_operation(get_port_opt());
    }
    else
    {
        //授权时间失效,不允许使能端口
        port_operation(0);
    }

    uint8_t is_write = false;
    while(1)
    {
        if(xQueueReceive( flash_operation_queue, &opeartion, 200))
        {
            if(FLASH_TIME_REMAIN == opeartion.type)
            {
                if(0 == time_remain && opeartion.time_remain)
                {
                    //恢复端口打开状态
                    port_operation(port);
                }
                if( 0 == opeartion.time_remain)
                {
                    //关闭所有端口
                    port_operation(0);
                }

                elog_warn("flash update time remain");
                time_remain = opeartion.time_remain;
                is_write = true;
                
            }
            else if(FLASH_PIN_MAP == opeartion.type)
            {
                
                port = opeartion.port;
                is_write = true;
                elog_warn("flash update port");
                
            }
            if(true == is_write)
            {
                is_write = false;
                elog_warn("port:0x%08x time remain:%d", port, time_remain);
                store_msg_generate(&store, port , time_remain);
                store_msg_write(&store);
            }
        }



//         {
//             radio_operation_t operation;
//             operation.type = RADIO_SEND;
//             rf_msg_send_notify(operation);
//         }
//
//         if((++cnt % 3) == 0)
//         {
//             flash_operation_t operation;
//             operation.type = FLASH_TIME_REMAIN;
//             operation.time_remain = cnt;
//             flash_operation_notify(operation);
//         }
    }
}


void rf_msg_receiver_success_notify(radio_operation_t oper)
{
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  xQueueSendFromISR( radio_operation_queue,  &oper, &xHigherPriorityTaskWoken );
  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

void rf_msg_send_notify(radio_operation_t oper)
{
  xQueueSend(radio_operation_queue, &oper, 10);
}

void rf_msg_send_success_notify(void)
{
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  vTaskNotifyGiveFromISR( rf_send_task_handler, &xHigherPriorityTaskWoken );
  portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

void rf_msg_send_wait_success(void)
{
    xTaskNotifyStateClear( NULL );
    ulTaskNotifyTake(pdTRUE, 3);
}

void flash_operation_notify_from_ISR(flash_operation_t oper)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xQueueSendFromISR( flash_operation_queue,  &oper, &xHigherPriorityTaskWoken );
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

void flash_operation_notify(flash_operation_t oper)
{
    xQueueSend( flash_operation_queue,  &oper, 10 );
}


uint32_t actual_idle_tick = 0;
uint32_t prv_idle_tick = 0;
uint32_t second_tick = 0;
//idle任务中开一个判断,只要收到就更新超时时间,只要时间到了,就关闭所有端口

elab_device_t* led_instance = NULL;
void vApplicationIdleHook( void )
{
	#if EN_IWDOG	
		/*wdg reload*/
		WDOG_Feed();
	#endif
	
    actual_idle_tick = xTaskGetTickCount();
	/*1000ms周期执行*/
    if((actual_idle_tick - prv_idle_tick) >= 1000)
	{
		prv_idle_tick = actual_idle_tick;
        second_tick++;
        if( NULL == led_instance )
        {
            led_instance = device_find("led");
            elab_pin_set_mode(led_instance, PIN_MODE_OUTPUT_PP);
        }
        if(second_tick % 2)
        {
            elab_pin_set_status(led_instance, 1);
        }
        else
        {   
            elab_pin_set_status(led_instance, 0);
        }
	}

//    if( 0 == (actual_idle_tick % 200) )
//    {
//        radio_operation_t operation;
//        operation.type = RADIO_SEND;
//        rf_msg_send_notify(operation);
//    }
//
//    if(0 == (actual_idle_tick % 500))
//    {
//        flash_operation_t operation;
//        operation.type = FLASH_TIME_REMAIN;
//        operation.time_remain = actual_idle_tick;
//        flash_operation_notify(operation);
//    }

}

#if 0
/************************************************
 * @brief    vSysGuardTask
 * @Author   ocamar
 * @DateTime 2021-07-20
 * @version  v1.0
 * @param    parameter              [description]
*************************************************/

//printf("=================================================\r\n");
//printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
//vTaskList((char *)&pcWriteBuffer);
//printf("%s\r\n", pcWriteBuffer);
//printf("\r\n 任务名 运行计数 使用率\r\n");
//vTaskGetRunTimeStats((char *)&pcWriteBuffer);
//printf("%s\r\n", pcWriteBuffer);
//sprintf( pcWriteBuffer, "Current free heap %d bytes, minimum ever free heap %d bytes\r\n", ( int ) xPortGetFreeHeapSize(), ( int ) xPortGetMinimumEverFreeHeapSize() );



uint8_t pcWriteBuffer[120];
void vSysGuardTask(void *pvParameters)
{
    (void) pvParameters;
    TickType_t xLastWakeTime;
    const TickType_t xPeriod = pdMS_TO_TICKS( 1000 );
    xLastWakeTime = xTaskGetTickCount();
    while(1)
    {
        //sprintf( pcWriteBuffer, "Current free space %d , Total space %d \r\n", ( int ) EventManage_Handler.idle.nodeCount, 34 );
        //sprintf( pcWriteBuffer, "free heap %d B, minimum free heap %d B\r\n", ( int ) xPortGetFreeHeapSize(), ( int ) xPortGetMinimumEverFreeHeapSize() );


//        sprintf(pcWriteBuffer, "free heap %d B, minimum free heap %d B\r\nEvent minimum free space %d , Total space %d \r\n", ( int ) xPortGetFreeHeapSize(), ( int ) xPortGetMinimumEverFreeHeapSize() , tListStatistical(&EventManage_Handler.idle, 0), 34);

//        DEBUG(pcWriteBuffer, false);
        //taskENTER_CRITICAL();
        //LEUART_Dma_Tx_String(pcWriteBuffer, false);
        //taskEXIT_CRITICAL();

        WDOG_Feed();
        vTaskDelayUntil( &xLastWakeTime, xPeriod );
    }
}
#endif

/**** Copyright (C)2021 OCAMAR. All Rights Reserved **** END OF FILE ****/
